﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Forms;
using System.Windows.Shapes;
using Microsoft.Surface.Presentation;
using Microsoft.Surface.Presentation.Controls;

namespace BoardGamePlayer
{
    /// <summary>
    /// Interaction logic for Deck.xaml
    /// </summary>
    public partial class Deck : ScatterViewItem
    {

        private Stack<Card> cardStack;

        public Deck()
        {
            InitializeComponent();
            cardStack = new Stack<Card>();
        }

        public Deck(string cardsDirectory)
        {
            InitializeComponent();
            cardStack = new Stack<Card>();
            loadCards(cardsDirectory, "");
            updateCardCount();
            updateDeckTopImage();
        }

        public Deck(string cardsDirectory, string backImageSource) 
        {
            InitializeComponent();
            cardStack = new Stack<Card>();
            loadCards(cardsDirectory, backImageSource);
            updateCardCount();
            updateDeckTopImage();
        }

        public Deck(ICollection<Card> cards)
        {
            InitializeComponent();
            cardStack = new Stack<Card>(cards);
            updateCardCount();
            updateDeckTopImage();
        }

        public ScatterView drawTarget
        {
            get { return (Parent as ScatterView); }
        }

        private void loadCards(string cardFolder, string backImageSource)
        {

            List<String> imgStrings = new List<string>();
            cardStack.Clear();
            try
            {
                string[] pngImages = System.IO.Directory.GetFiles(cardFolder, "*.png");
                string[] jpgImages = System.IO.Directory.GetFiles(cardFolder, "*.jpg");
                string[] gifImages = System.IO.Directory.GetFiles(cardFolder, "*.gif");

                foreach (string cardStr in pngImages)
                {
                    Card c = new Card(cardStr, backImageSource);
                    cardStack.Push(c);
                }
                foreach (string cardStr in jpgImages)
                {
                    Card c = new Card(cardStr, backImageSource);
                    cardStack.Push(c);
                }
                foreach (string cardStr in gifImages)
                {
                    Card c = new Card(cardStr, backImageSource);
                    cardStack.Push(c);
                }
            }
            catch (System.ArgumentException e)
            {
                System.Windows.Forms.MessageBox.Show("Invalid folder path");
            }
        }

        public void drawCard()
        {

            if (cardStack.Count <= 0) 
            {
                return;
            }
            if (cardStack.Count > 1)
            {
                Card c = cardStack.Pop();
                c.Width = this.ActualWidth;
                c.Height = this.ActualHeight;
                updateCardCount();
                updateDeckTopImage();
                Point drawPoint = new Point(this.ActualCenter.X + this.ActualWidth, this.ActualCenter.Y);
                if (drawPoint.X < 0 ||
                    drawPoint.X > drawTarget.ActualWidth||
                    drawPoint.Y <0 ||
                    drawPoint.Y > drawTarget.ActualHeight)
                {
                    drawPoint.X = drawTarget.ActualWidth / 2;
                    drawPoint.Y = drawTarget.ActualHeight / 2;
                }
                c.Center = drawPoint;
                c.Orientation = this.ActualOrientation;
                drawTarget.Items.Add(c);
            }
            if (cardStack.Count <= 1) 
            {
                Card c = cardStack.Pop();
                if (c != null)
                {
                    c.Center = this.Center;
                    c.Orientation = this.Orientation;
                    c.Width = this.ActualWidth;
                    c.Height = this.ActualHeight;
                    drawTarget.Items.Add(c);
                }
                (Parent as ScatterView).Items.Remove(this);
            }
        }

        public void shuffleDeck()
        {
            Random r = new Random((int)DateTime.Now.Millisecond);
            Card[] cardArray = cardStack.ToArray();
            for (int i = 0; i < cardArray.Count(); i++)
            {
                int swapIndex = r.Next(0, cardStack.Count - 1);
                Card other = cardArray[swapIndex];
                Card cur = cardArray[i];
                cardArray[i] = other;
                cardArray[swapIndex] = cur;
            }
            cardStack.Clear();
            foreach (Card c in cardArray)
            {
                c.IsFaceUp = false;
                cardStack.Push(c);
            }
            updateDeckTopImage();
        }

        public void flipDeck() 
        {
            Stack<Card> newStack = new Stack<Card>();
            while (cardStack.Count > 0) 
            {
                Card c = cardStack.Pop();
                c.IsFaceUp = !c.IsFaceUp;
                newStack.Push(c);
            }
            cardStack = newStack;
            updateDeckTopImage();
        }

        private void updateCardCount()
        {
            cardCountLabel.Content = cardStack.Count.ToString();
        }

        private void updateDeckTopImage() 
        {
            if (cardStack.Count > 0)
            {
                deckTopImage.Source = cardStack.Peek().FaceUpImage;
            }
            else 
            {
                deckTopImage.Source = null;
            }

        }

        private void shuffleButton_Click(object sender, RoutedEventArgs e)
        {
            shuffleDeck();
            optionsExpander.IsExpanded = false;
        }

        private void flipDeckButton_Click(object sender, RoutedEventArgs e)
        {
            flipDeck();
            optionsExpander.IsExpanded = false;
        }

        protected override void OnManipulationStarting(ManipulationStartingEventArgs e)
        {
            BeginDragDrop(this);
            base.OnManipulationStarting(e);
        }

        private void ScatterViewItem_Drop(object sender, SurfaceDragDropEventArgs e)
        {
            if (e.Cursor.Data is Card)
            {
                //put the card on top of the deck
                Card droppedCard = e.Cursor.Data as Card;
                cardStack.Push(droppedCard);
                updateDeckTopImage();
                updateCardCount();
            }
            else if (e.Cursor.Data is Deck) 
            {
                //combine the decks into one deck
                //use this location and orientation with the dragged deck's items on top
                Card[] theseCards = cardStack.ToArray();
                Card[] thoseCards = (e.Cursor.Data as Deck).cardStack.ToArray();
                Stack<Card> allCards = new Stack<Card>();
                foreach (Card c in thoseCards) 
                {
                    c.Width = this.ActualWidth;
                    c.Height = this.ActualHeight;
                    allCards.Push(c);
                }
                foreach (Card c in theseCards)
                {
                    c.Width = this.ActualWidth;
                    c.Height = this.ActualHeight;
                    allCards.Push(c);
                }
                Deck newDeck = new Deck(allCards.ToArray());
                newDeck.Width = this.ActualWidth;
                newDeck.Height = this.ActualHeight;
                newDeck.Center = this.ActualCenter;
                newDeck.Orientation = this.ActualOrientation;
                drawTarget.Items.Add(newDeck);
                (Parent as ScatterView).Items.Remove(this);
            }
            else
            {
                //just put it back where it came from
                (e.Cursor.DragSource as ScatterView).Items.Add(e.Cursor.Data);
            }

        }

        private void optionsExpander_TapGesture(object sender, TouchEventArgs e)
        {
            optionsExpander.IsExpanded = !optionsExpander.IsExpanded;
        }

        private void SurfaceButton_Click(object sender, RoutedEventArgs e)
        {
            optionsExpander.IsExpanded = false;
            drawCard();
        }

    }
}
